package com.momomian.common.collection;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author momomian
 * @date 2021/12/30
 */
public class CollectionUtils {

    private static final int SPILT_SIZE = 1000;


    public static <T> T first(List<T> target) {
        if (target == null || target.size() == 0) {
            return null;
        }
        return target.get(0);
    }

    public static boolean isEmpty(Collection<?> target) {
        if (target == null) {
            return true;
        }
        return target.size() == 0;
    }

    public static boolean isEmpty(Map<?, ?> map) {
        return map == null || map.isEmpty();
    }


    /**
     * Map<String, Set<String>> 深拷贝
     *
     * @param paramsMap 需要被拷贝的map
     * @return 拷贝后的map
     */
    public static Map<String, Set<String>> mapCopy(Map<String, Set<String>> paramsMap) {
        if (paramsMap == null) {
            return null;
        }
        Map<String, Set<String>> resultMap = new HashMap<>(paramsMap.size() + 1);

        for (Map.Entry<String, Set<String>> next : paramsMap.entrySet()) {
            String key = next.getKey();
            Set<String> set = paramsMap.get(key);
            if (set == null) {
                continue;
            }
            Set<String> setTemp = new HashSet<>(set);
            resultMap.put(key, setTemp);
        }
        return resultMap;
    }

    /**
     * 返回map中所有set的长度和
     *
     * @param map Map<String, Set<String>>
     * @return int
     */
    public static int getInnerAllSize(Map<String, Set<String>> map) {
        int allSize = 0;
        for (Map.Entry<String, Set<String>> entry : map.entrySet()) {
            allSize += entry.getValue().size();
        }
        return allSize;
    }

    /**
     * 集合转换
     * Map<String, List<String>> ---> Map <String, Set<String>>
     *
     * @param areaMap
     * @return Map <String, Set<String>>
     */
    public static Map<String, Set<String>> listMapToSetMap(Map<String, List<String>> areaMap) {
        Map<String, Set<String>> map = new HashMap<>();
        areaMap.forEach((keyTemp, valueTemp) -> map.put(keyTemp, new HashSet<>(valueTemp)));
        return map;
    }

    /**
     * 集合转换
     * Map <String, Set<String>> ---> Map<String, List<String>>
     *
     * @param areaMap
     * @return Map<String, List < String>>
     */
    public static Map<String, List<String>> setMapToListMap(Map<String, Set<String>> areaMap) {
        Map<String, List<String>> map = new HashMap<>();
        areaMap.forEach((keyTemp, valueTemp) -> map.put(keyTemp, new ArrayList<String>(valueTemp)));
        return map;
    }

    /***
     *  分割集合，默认分1000个
     **/
    public static <T> List<List<T>> spiltList(List<T> list) {
        return spiltList(list, SPILT_SIZE);
    }

    /***
     *  按照一定的长度分割集合
     **/
    public static <T> List<List<T>> spiltList(List<T> list, int spiltSize) {
        return ListUtil.split(list, spiltSize);
    }

    /***
     *  根据数据列表长度计算分割列表的单列表长度
     **/
    public static int calcSplitSize(int dataSize) {
        int spiltSize = 10000;
        try {
            //1-1千范围
            if (dataSize <= 1000) {
                return dataSize;
            }
            //1千-1百万范围
            if (dataSize <= 1000000) {
                return spiltSize;
            }
            //1百万-到2百万
            if (dataSize <= 2000000) {
                return spiltSize * 2;
            }
            //2百万-到3百万
            if (dataSize <= 3000000) {
                return spiltSize * 3;
            }
            //3百万-到4百万
            if (dataSize <= 4000000) {
                return spiltSize * 4;
            }
        } catch (Exception e) {
            return spiltSize;
        }
        //超过400万
        return spiltSize * 5;
    }


    /**
     * 使用HashSet实现List去重(无序)
     */
    public static List<String> removeDuplicationByHashSet(List<String> list) {
        HashSet<String> set = new HashSet<>(list);
        //把List集合所有元素清空
        list.clear();
        //把HashSet对象添加至List集合
        list.addAll(set);
        return list;
    }

    /**
     * @return java.util.Map<K, V>
     * @See listToMap(list, UserVo : : getUserId, userVo - > userVo);
     * @See listToMap(list, UserVo : : getUserId, UserVo : : getUserName);
     * @Description List<T>转Map<K,V>
     * @Param srcList 源集合
     * @Param keyMapper key函数
     * @Param valMapper value函数
     **/
    public static <T, K, V> Map<K, V> listToMap(Collection<T> srcList, Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends V> valMapper) {
        if (CollUtil.isEmpty(srcList)) {
            return null;
        }
        return srcList.stream().collect(Collectors.toMap(keyMapper, valMapper, (k1, k2) -> k2));
    }

    /**
     * @return java.util.List<K>
     * @See listToStrList(list, UserVo : : getUserId);
     * @Description List<T>转List<K>
     * @Param srcList 源集合
     * @Param keyMapper key函数
     **/
    public static <T, K> List<K> listToStrList(Collection<T> srcList, Function<? super T, ? extends K> idMapper) {
        if (CollUtil.isEmpty(srcList)) {
            return null;
        }
        return srcList.stream().map(idMapper).distinct().collect(Collectors.toList());
    }

    /**
     * @return java.util.List<K>
     * @See  listToStrList(list, UserVo : : getUserId, e - > e.getTaskId ()!=null);
     * @description List<T>转List<K>
     * @param srcList 源集合
     * @param idMapper key函数
     * @param filter 过滤函数
     **/
    public static <T, K> List<K> listToStrList(Collection<T> srcList, Function<? super T, ? extends K> idMapper, Predicate<? super T> filter) {
        if (CollUtil.isEmpty(srcList)) {
            return null;
        }
        if (filter == null) {
            return listToStrList(srcList, idMapper);
        }
        return srcList.stream().filter(filter).map(idMapper).distinct().collect(Collectors.toList());
    }

    /**
     * 校验一个map的key是否为 某值
     *
     */
    public static <T> boolean isA(Map<String, T> map, String target) {
        if (isEmpty(map) || map.size() != 1) {
            return false;
        }
        return map.containsKey(target);
    }

}
